package com.proj.android.canyondefense.core.gl;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.opengles.GL10;

import com.proj.android.canyondefense.core.impl.GLGraphics;

public class Vertices {
    private final GLGraphics _glGraphics;
    private final boolean _hasColor;
    private final boolean _hasTexCoords;
    private final int _vertexSize;
    private final int[] _tmpBuffer;
    private final IntBuffer _vertices;
    private final ShortBuffer _indices;
    
    public Vertices(GLGraphics glGraphics, int maxVertices, int maxIndices, boolean hasColor, boolean hasTexCoords) {
        this._glGraphics = glGraphics;
        this._hasColor = hasColor;
        this._hasTexCoords = hasTexCoords;
        this._vertexSize = (2 + (hasColor?4:0) + (hasTexCoords?2:0)) * 4;
        this._tmpBuffer = new int[maxVertices * _vertexSize / 4];
        
        ByteBuffer buffer = ByteBuffer.allocateDirect(maxVertices * _vertexSize);
        buffer.order(ByteOrder.nativeOrder());
        _vertices = buffer.asIntBuffer();
        
        if(maxIndices > 0) {
            buffer = ByteBuffer.allocateDirect(maxIndices * Short.SIZE / 8);
            buffer.order(ByteOrder.nativeOrder());
            _indices = buffer.asShortBuffer();
        } else {
            _indices = null;
        }            
    }
    
    public void setVertices(float[] vertices, int offset, int length) {
        this._vertices.clear();
        int len = offset + length;
        for(int i = offset, j = 0; i < len; i++, j++) { 
            _tmpBuffer[j] = Float.floatToRawIntBits(vertices[i]);
        }
        this._vertices.put(_tmpBuffer, 0, length);
        this._vertices.flip();
    }
    
    public void setIndices(short[] indices, int offset, int length) {
        this._indices.clear();
        this._indices.put(indices, offset, length);
        this._indices.flip();
    }
    
	public void bind() {
	    GL10 gl = _glGraphics.getGL();
	    
	    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
	    _vertices.position(0);
	    gl.glVertexPointer(2, GL10.GL_FLOAT, _vertexSize, _vertices);
	    
	    if(_hasColor) {
	        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
	        _vertices.position(2);
	        gl.glColorPointer(4, GL10.GL_FLOAT, _vertexSize, _vertices);
	    }
	    
	    if(_hasTexCoords) {
	        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
	        _vertices.position(_hasColor?6:2);
	        gl.glTexCoordPointer(2, GL10.GL_FLOAT, _vertexSize, _vertices);
	    }
	}
	
	public void draw(int primitiveType, int offset, int numVertices) {        
	    GL10 gl = _glGraphics.getGL();
	    
	    if(_indices!=null) {
	        _indices.position(offset);
	        gl.glDrawElements(primitiveType, numVertices, GL10.GL_UNSIGNED_SHORT, _indices);
	    } else {
	        gl.glDrawArrays(primitiveType, offset, numVertices);
	    }        
	}
	
	public void unbind() {
	    GL10 gl = _glGraphics.getGL();
	    if(_hasTexCoords)
	        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
	
	    if(_hasColor)
	        gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
	}
}
